package com.fdh.myjdbcutil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * jdbc工具类
 *
 * <p>技术有限,写的一般,能用就行</p>
 *
 * <p>
 * 封装类请使用带upgrade的方法
 * </p>
 *
 * <p>
 * 更新内容:
 * 列名解析优化
 * </p>
 *
 * @author fdh 2025.1.21 20.42
 * @version 3.2
 */
public class MyJdbcUtil {
    private String url;
    private String user;
    private String password;
    private String driver;
    private static boolean isUseErrorStack = false; //是否启用错误栈输出,方便定位错误
    private static boolean isUseReminderMessage = true; //是否启用错误提醒,方便了解错误类型和内容
    private static boolean isPrintSql = false; //是否打印sql语句
    private boolean isEnableThrowError = false; //当工具类出错时是否抛出异常
    private Connection conn;
    private Statement statement;
    private static MyJdbcUtil instance;

    /**
     * 获取是否使用错误栈
     *
     * @return 是否使用
     */
    public boolean getIsUseErrorStack() {
        return isUseErrorStack;
    }

    /**
     * 获取是否使用错误提醒
     *
     * @return 是否使用
     */
    public boolean getIsUseReminderMessage() {
        return isUseReminderMessage;
    }

    /**
     * 是否启用错误栈输出,默认false
     *
     * @param isUseErrorStack 是否启用错误栈
     */
    public void setIsUseErrorStack(boolean isUseErrorStack) {
        MyJdbcUtil.isUseErrorStack = isUseErrorStack;
    }

    /**
     * 是否启用提醒信息输出,默认true
     *
     * @param isUseReminderMessage 是否启用提醒信息输出
     */
    public void setIsPrintErrorMessage(boolean isUseReminderMessage) {
        MyJdbcUtil.isUseReminderMessage = isUseReminderMessage;
    }

    /**
     * 当工具类出错时是否抛出异常
     *
     * @return 是否抛出
     */
    public boolean getIsEnableThrowError() {
        return isEnableThrowError;
    }

    /**
     * 当工具类出错时是否抛出异常,开启后所有操作一旦出错就会抛出RuntimeException
     *
     * @param isEnableThrowError 是否抛出
     */
    public void setIsEnableThrowError(boolean isEnableThrowError) {
        this.isEnableThrowError = isEnableThrowError;
    }

    /**
     * 是否打印sql语句,默认false
     *
     * @return 是否打印sql语句
     */
    public boolean getIsPrintSql() {
        return isPrintSql;
    }

    /**
     * 是否打印sql语句,默认false
     *
     * @param isPrintSql 是否打印sql语句
     */
    public void setIsPrintSql(boolean isPrintSql) {
        MyJdbcUtil.isPrintSql = isPrintSql;
    }

    /**
     * 查看数据库连接情况
     *
     * @return 是否连接, true为连接成功, false为断连
     */
    public boolean connectionState() {
        if (conn == null)
            return false;
        try {
            return !conn.isClosed();
        } catch (Exception e) {
            return false;
        }
    }

    //连接线程,用于异步连接数据库
    private final Thread connectThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                conn = DriverManager.getConnection(url, user, password);
                if (conn == null) {
                    throw new Exception("url,user,pwd错误");
                }
                statement = conn.createStatement();
            } catch (Exception e) {
                if (isUseReminderMessage)
                    System.out.println("提醒:数据库连接失败:" + e.getMessage());
                if (isEnableThrowError)
                    throw new RuntimeException(e);
                if (isUseErrorStack)
                    e.printStackTrace();
            }
        }
    });

    /**
     * 事务处理接口,用于事务处理
     * <p/>
     * 事务中不建议使用{@link MyJdbcUtil#getInstance()},推荐使用work的jdbcUtil参数
     */
    public interface Work {
        /**
         * 事务的主体
         *
         * @param jdbcUtil 当前jdbc工具类的实例
         * @throws Exception 触发回滚的错误
         */
        void work(MyJdbcUtil jdbcUtil) throws Exception;

        /**
         * 当出现错误时执行,回滚会自动执行,该函数可执行其他操作
         *
         * @param jdbcUtil 当前jdbc工具类的实例
         */
        void error(MyJdbcUtil jdbcUtil);
    }

    /**
     * 标准事务处理方法,会在当前连接上处理
     *
     * <p>如果事务出现问题,直接手动抛出异常即可,会被自动捕获然后回滚事务</p>
     *
     * @param work 主体事务
     * @return 是否成功完成
     * @throws RuntimeException 事务出错
     */
    public boolean standardTransactionModel(Work work) throws RuntimeException {
        boolean isSuccess = false;
        boolean isEnableThrowError_clone = isEnableThrowError;
        try {
            setConnAutoCommit(false);
            setIsEnableThrowError(true);

            work.work(this); //事务主体

            commit();
            isSuccess = true;
        } catch (Exception e) {
            work.error(this);
            if (isUseReminderMessage)
                System.out.println("提醒:事务处理问题:" + e.getMessage());
            if (isEnableThrowError) {
                rollBack();
                throw new RuntimeException(e);
            }
            if (isUseErrorStack)
                e.printStackTrace();
            rollBack();
        } finally {
            setConnAutoCommit(true);
            setIsEnableThrowError(isEnableThrowError_clone);
        }
        return isSuccess;
    }

    /**
     * 标准事务处理方法,会在新的连接上处理,会自动关闭连接
     *
     * <p>如果事务出现问题,直接手动抛出异常即可,最后会被自动捕获然后回滚事务</p>
     *
     * @param work 主体事务
     * @return 是否成功完成
     * @throws RuntimeException 事务出错
     */
    public boolean standardTransactionModel_NewInstance(Work work) throws RuntimeException {
        MyJdbcUtil newInstance = getNewInstance();
        try {
            newInstance.connectMySQL();
            return newInstance.standardTransactionModel(work);
        } finally {
            newInstance.close();
        }
    }

    /**
     * 单例模式
     *
     * @return 当前对象的实例
     */
    public static MyJdbcUtil getInstance() {
        return instance;
    }


    /**
     * 获取新的实例,不主动连接数据库,记得主动关闭连接
     * <br/>
     * 地址,用户,密码,驱动采用单例的信息
     *
     * <p>注意:{@link MyJdbcUtil#getInstance()} 是单例模式,也就是新的实例不会覆盖旧实例</p>
     *
     * @return 新的实例
     */
    public MyJdbcUtil getNewInstance() {
        return getNewInstance(instance.url, instance.user, instance.password, instance.driver);
    }


    /**
     * 获取新的实例,驱动默认mysql8,不主动连接数据库,记得主动关闭连接
     *
     * <p>注意:{@link MyJdbcUtil#getInstance()} 是单例模式,也就是新的实例不会覆盖单例instance</p>
     *
     * @param url      地址
     * @param user     用户名
     * @param password 密码
     * @return 新的实例
     */
    public static MyJdbcUtil getNewInstance(String url, String user, String password) {
        return new MyJdbcUtil(url, user, password);
    }

    /**
     * 获取新的实例,不主动连接数据库,记得主动关闭连接
     *
     * <p>注意:{@link MyJdbcUtil#getInstance()} 是单例模式,也就是新的实例不会覆盖单例instance</p>
     *
     * @param url      地址
     * @param user     用户名
     * @param password 密码
     * @param driver   驱动
     * @return 新的实例
     */
    public static MyJdbcUtil getNewInstance(String url, String user, String password, String driver) {
        return new MyJdbcUtil(url, user, password, driver);
    }

    /**
     * 设置连接信息
     *
     * @param url      地址
     * @param user     用户名
     * @param password 密码
     */
    public void setConnectionInfo(String url, String user, String password) {
        this.url = url;
        this.user = user;
        this.password = password;
    }

    /**
     * 获取数据库异步连接的线程
     *
     * @return 数据库异步连接的线程
     */
    public Thread getConnectThread() {
        return connectThread;
    }

    /**
     * 等待数据库异步连接成功
     */
    public void waitForConnect() {
        try {
            connectThread.join();
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:连接线程问题:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
    }

    /**
     * 获取连接
     *
     * <p>
     * 不推荐获取'连接'来操作数据库,因为这个连接是本工具类的核心,不当操作可能导致工具类错误
     * <p/>
     *
     * @return 数据库的连接
     */
    public Connection getConnection() {
        return conn;
    }


    /**
     * 关闭数据库
     */
    public void close() {
        try {
            ResultSetManager.closeAllResultSet();
            statement.close();
            conn.close();
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库关闭失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
    }

    /**
     * 设置是否自动提交,默认开启
     *
     * @param autoCommit 是否自动提交
     */
    public boolean setConnAutoCommit(boolean autoCommit) {
        try {
            conn.setAutoCommit(autoCommit);
            return true;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:设置自动提交出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return false;
    }

    /**
     * 提交操作
     */
    public boolean commit() {
        try {
            conn.commit();
            return true;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:提交出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return false;
    }

    /**
     * 回滚操作
     */
    public boolean rollBack() {
        try {
            conn.rollback();
            return true;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:回滚出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return false;
    }

    /**
     * 连接数据库
     */
    public MyJdbcUtil connectMySQL() {
        connectMySQL(false);
        return this;
    }

    /**
     * 连接数据库
     *
     * @param isUseMultithreadingConnectDatabase 是否使用异步连接
     */
    public void connectMySQL(boolean isUseMultithreadingConnectDatabase) {
        if (isUseMultithreadingConnectDatabase) {
            if (isUseReminderMessage)
                System.out.println("提醒:开始异步连接数据库");
            connectThread.start();
        } else {
            connectThread.run();
        }
    }

    /**
     * 初始化类,驱动默认为mysql8的,默认不直接连数据库
     *
     * @param url      数据库的连接地址
     * @param user     用户名
     * @param password 密码
     */
    public MyJdbcUtil(String url, String user, String password) {
        this(url, user, password, "com.mysql.cj.jdbc.Driver", false);
    }

    /**
     * 初始化类,驱动默认为mysql8的
     *
     * @param url               数据库的连接地址
     * @param user              用户名
     * @param password          密码
     * @param isConnectDatabase 是否直接连接数据库
     */
    public MyJdbcUtil(String url, String user, String password, boolean isConnectDatabase) {
        this(url, user, password, "com.mysql.cj.jdbc.Driver", isConnectDatabase);
    }

    /**
     * 初始化类,默认不直接连接数据库
     *
     * @param url      数据库的连接地址
     * @param user     用户名
     * @param password 密码
     * @param driver   驱动
     */
    public MyJdbcUtil(String url, String user, String password, String driver) {
        this(url, user, password, driver, false);
    }


    /**
     * 初始化类
     *
     * @param url               数据库的连接地址
     * @param user              用户名
     * @param password          密码
     * @param driver            驱动类名
     * @param isConnectDatabase 是否直接连接数据库
     */
    public MyJdbcUtil(String url, String user, String password, String driver, boolean isConnectDatabase) {
        if (instance == null) {
            instance = this;
            try {
                Class.forName(driver);
            } catch (Exception e) {
                if (isUseReminderMessage)
                    System.out.println("提醒:构造错误:" + e.getMessage());
                if (isEnableThrowError)
                    throw new RuntimeException(e);
                if (isUseErrorStack)
                    e.printStackTrace();
            }
        }
        setConnectionInfo(url, user, password);
        this.driver = driver;
        if (isConnectDatabase) {
            connectMySQL(false);
        }
    }

    /**
     * 显示数据库操作sql信息
     *
     * @param title 标题
     * @param sql   sql语句
     * @param map   映射数组
     */
    private void printSql(String title, String sql, Object[] map) {
        if (isPrintSql) {
            System.out.println("***************" + title + "***************");
            if (sql != null)
                System.out.println(sql);
            if (map != null)
                System.out.println(Arrays.asList(map));
            System.out.println("***************************************");
        }
    }

    //region 基本增删改

    /**
     * 查询语句执行
     *
     * @param sql sql语句
     * @return 查询结果集, 如果查询失败返回null
     */
    public IAnalysisResultSet selectSql(String sql) {
        try {
            printSql("selectSql", sql, null);
            ResultSet resultSet = statement.executeQuery(sql);
            ResultSetManager.addNewResultSet(resultSet, null);
            return new AnalysisResultSetImpl(resultSet);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库查询失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 增加,修改,删除的数据操作
     *
     * @param sql sql语句
     * @return 影响的行数, 错误返回-1
     */
    public int updateSql(String sql) {
        try {
            printSql("updateSql", sql, null);
            return statement.executeUpdate(sql);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库增删改失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 执行sql语句,一般用来执行数据库操作
     *
     * @param sql sql语句
     * @return 是否执行成功
     */
    public boolean executeSql(String sql) {
        try {
            printSql("executeSql", sql, null);
            return statement.execute(sql);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库sql命令失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return false;
    }

    /**
     * 兼容sql的‘?’占位符,插入,删除,更新数据,map数组里的元素应当和'?'一一对应
     *
     * @param sql 增强sql
     * @param map 映射数组
     * @return 返回插入行数
     */
    public int updateSql(String sql, Object[] map) {
        try {
            printSql("updateSql", sql, map);
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            for (int i = 0; i < map.length; i++) {
                preparedStatement.setObject(i + 1, map[i]);
            }
            int i = preparedStatement.executeUpdate();
            preparedStatement.close();
            return i;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库增删改失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 兼容sql的‘?’占位符,查询数据,map数组里的元素应当和'?'一一对应
     *
     * @param sql 增强sql
     * @param map 映射数组
     * @return 结果集, 如果失败则返回null
     */
    public IAnalysisResultSet selectSql(String sql, Object[] map) {
        try {
            printSql("selectSql", sql, map);
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            for (int i = 0; i < map.length; i++) {
                preparedStatement.setObject(i + 1, map[i]);
            }
            ResultSet resultSet = preparedStatement.executeQuery();
            ResultSetManager.addNewResultSet(resultSet, preparedStatement);
            return new AnalysisResultSetImpl(resultSet);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库增删改失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    //endregion

    //region 实体类数据库操作

    /**
     * 字段过滤器,过滤出指定类型的字段
     *
     * @param fields 需要过滤的字段
     * @param types  字段过滤类型
     * @return 过滤好的字段
     */
    private Field[] fieldFilter(Field[] fields, ColumnField.Type[] types) {
        ArrayList<Field> list = new ArrayList<>();
        for (Field field : fields) {
            ColumnField annotation = field.getAnnotation(ColumnField.class);
            if (annotation != null) {
                boolean flag = false;
                for (ColumnField.Type type : types) {
                    if (annotation.type() == type) {
                        flag = true;
                        break;
                    }
                }
                if (flag) {
                    list.add(field);
                }
            }
        }
        return list.toArray(new Field[0]);
    }

    /**
     * 获取表名
     *
     * @param entity 实体类
     * @param <T>    实体类类型
     * @return 表名
     */
    private <T extends IMyEntity> String getTableNameFromClass(T entity) {
        String tableName;
        TableName tableNameAnno = entity.getClass().getAnnotation(TableName.class);
        if (tableNameAnno != null) {
            tableName = tableNameAnno.value();
        } else {
            tableName = classNameToTableName(entity);
        }
        return tableName;
    }

    /**
     * 获取数据库列名
     *
     * @param field 字段
     * @return 数据库列名
     */
    private String getColNameFromField(Field field) {
        ColumnField annotation = field.getAnnotation(ColumnField.class);
        if (annotation.colName().isEmpty()) {
            return littleHumpReplace(field.getName());
        } else {
            return annotation.colName();
        }
    }


    /**
     * 通过实体类插入数据
     *
     * @param entity 实体类
     * @param <T>    实体类类型
     * @return 影响的行数
     */
    public <T extends IMyEntity> int insertSql(T entity) {
        Field[] fields = entity.getClass().getFields();
        if (fields.length == 0) {
            return 0;
        }
        fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.GET, ColumnField.Type.ALL});
        try {
            String tableName = getTableNameFromClass(entity);
            int n = fields.length;
            StringBuilder sql = new StringBuilder("INSERT INTO " + tableName + "(");
            Object[] vals = new Object[n];
            String colName;
            for (int i = 0; i < n - 1; i++) {
                colName = getColNameFromField(fields[i]);
                sql.append(colName).append(",");
                vals[i] = getFieldValue(entity, fields[i], null, false);
//                if (fields[i].getAnnotation(JSONField.class) != null) {
//                    vals[i] = JSONUtil.objectToJson(fields[i].get(entity));
//                } else {
//                    vals[i] = fields[i].get(entity);
//                }
            }
            colName = getColNameFromField(fields[n - 1]);
            sql.append(colName).append(")");
            vals[n - 1] = getFieldValue(entity, fields[n - 1], null, false);
//            if (fields[n - 1].getAnnotation(JSONField.class) != null) {
//                vals[n - 1] = JSONUtil.objectToJson(fields[n - 1].get(entity));
//            } else {
//                vals[n - 1] = fields[n - 1].get(entity);
//            }
            sql.append(" VALUES(");
            for (int i = 0; i < n; i++) {
                sql.append("?");
                if (i != n - 1) {
                    sql.append(",");
                } else {
                    sql.append(")");
                }
            }
            return updateSql(sql.toString(), vals);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库插入失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 通过实体类列表批量插入数据
     *
     * @param entityList 实体类列表
     * @param <T>        实体类
     * @return 受影响的行数
     */
    public <T extends IMyEntity> int insertAllSql(List<T> entityList) {
        int count = 0;
        for (T entity : entityList) {
            int i = insertSql(entity);
            if (i == -1) {
                if (isUseReminderMessage)
                    System.out.println("提醒:批量插入出错:" + entity);
            } else {
                count += i;
            }
        }
        return count;
    }

    /**
     * 通过实体类插入数据
     *
     * <p>支持封装类</p>
     *
     * @param entity 实体类
     * @param <T>    实体类类型
     * @return 影响的行数
     */
    public <T extends IMyEntity> int insertSql_upgrade(T entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        if (fields.length == 0) {
            return 0;
        }
        fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.GET, ColumnField.Type.ALL});
        Method[] methods = entity.getClass().getMethods();
        try {
            String tableName = getTableNameFromClass(entity);
            StringBuilder sb = new StringBuilder("INSERT INTO " + tableName + "(");
            int count = fields.length;
            ArrayList<Object> vals = new ArrayList<>();
            String colName;
            for (int i = 0; i < count - 1; i++) {
                Field field = fields[i];
                Object fieldValue = getFieldValue(entity, field, methods, true);
                vals.add(fieldValue);
                colName = getColNameFromField(field);
                sb.append(colName).append(",");


//                SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
//                Method getter = setterAndGetterFilterResult.getter;
//                if (getter != null) {
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        vals.add(JSONUtil.objectToJson(getter.invoke(entity)));
//                    } else {
//                        vals.add(getter.invoke(entity));
//                    }
//                    colName = getColNameFromField(field);
//                    sb.append(colName).append(",");
//                }

//                for (Method m : methods) {
//                    if (m.getName().equalsIgnoreCase("get" + field.getName())) {
//                        if (field.getAnnotation(JSONField.class) != null) {
//                            vals.add(JSONUtil.objectToJson(m.invoke(entity)));
//                        } else {
//                            vals.add(m.invoke(entity));
//                        }
//                        colName = getColNameFromField(field);
//                        sb.append(colName).append(",");
//                        break;
//                    }
//                }
            }
            Field field = fields[count - 1];
            Object fieldValue = getFieldValue(entity, field, methods, true);
            vals.add(fieldValue);
            colName = getColNameFromField(field);
            sb.append(colName).append(")");
//            SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
//            Method getter = setterAndGetterFilterResult.getter;
//            if (getter != null) {
//                if (field.getAnnotation(JSONField.class) != null) {
//                    vals.add(JSONUtil.objectToJson(getter.invoke(entity)));
//                } else {
//                    vals.add(getter.invoke(entity));
//                }
//                colName = getColNameFromField(field);
//                sb.append(colName).append(")");
//            }

//            for (Method m : methods) {
//                if (m.getName().equalsIgnoreCase("get" + field.getName())) {
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        vals.add(JSONUtil.objectToJson(m.invoke(entity)));
//                    } else {
//                        vals.add(m.invoke(entity));
//                    }
//                    colName = getColNameFromField(field);
//                    sb.append(colName).append(")");
//                    break;
//                }
//            }
            sb.append(" VALUES(");
            count = vals.size();
            for (int i = 0; i < count; i++) {
                if (i != count - 1) {
                    sb.append("?").append(",");
                } else {
                    sb.append("?").append(")");
                }
            }
            return updateSql(sb.toString(), vals.toArray());
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据插入失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 通过实体类列表批量插入数据
     *
     * <p>支持封装类</p>
     *
     * @param entityList 实体类列表
     * @param <T>        实体类
     * @return 受影响的行数
     */
    public <T extends IMyEntity> int insertAllSql_upgrade(List<T> entityList) {
        int count = 0;
        for (T entity : entityList) {
            int i = insertSql_upgrade(entity);
            if (i == -1) {
                if (isUseReminderMessage) {
                    System.out.println("提醒:批量插入出错:" + entity);
                }
            } else {
                count += i;
            }
        }
        return count;
    }

    //废弃方法,实现繁琐复杂,思路不对
//    /**
//     * 查询一条数据，返回对应的实例
//     *
//     * @param sql
//     * @param entity
//     * @param <T>
//     */
//    public <T extends IMyEntity> T selectSql(String sql, T entity) {
//        ResultSet resultSet = selectSql(sql);
//        Field[] fields = entity.getClass().getDeclaredFields();
//        try {
//            resultSet.next();
//            for (int i = 0; i < fields.length; i++) {
//                if (fields[i].getType() == byte.class || fields[i].getType() == Byte.class) {
//                    fields[i].setByte(entity, resultSet.getByte(fields[i].getName()));
//                } else if (fields[i].getType() == short.class || fields[i].getType() == Short.class) {
//                    fields[i].setShort(entity, resultSet.getShort(fields[i].getName()));
//                } else if (fields[i].getType() == int.class || fields[i].getType() == Integer.class) {
//                    fields[i].setInt(entity, resultSet.getInt(fields[i].getName()));
//                } else if (fields[i].getType() == long.class || fields[i].getType() == Long.class) {
//                    fields[i].setLong(entity, resultSet.getLong(fields[i].getName()));
//                } else if (fields[i].getType() == float.class || fields[i].getType() == Float.class) {
//                    fields[i].setFloat(entity, resultSet.getFloat(fields[i].getName()));
//                } else if (fields[i].getType() == double.class || fields[i].getType() == Double.class) {
//                    fields[i].setDouble(entity, resultSet.getDouble(fields[i].getName()));
//                } else if (fields[i].getType() == boolean.class || fields[i].getType() == Boolean.class) {
//                    fields[i].setBoolean(entity, resultSet.getBoolean(fields[i].getName()));
//                } else if (fields[i].getType() == Date.class) {
//                    fields[i].set(entity, resultSet.getDate(fields[i].getName()));
//                } else if (fields[i].getType() == String.class) {
//                    fields[i].set(entity, resultSet.getString(fields[i].getName()));
//                } else {
//                    fields[i].set(entity, resultSet.getObject(fields[i].getName()));
//                }
//            }
//            return entity;
//        } catch (Exception e) {
//            System.out.println("提醒:数据库查询失败:" + e.getMessage());
//               if (isUseErrorStack) {
//                   e.printStackTrace();
//               }
//            return null;
//        }
//    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql(String, String[], IMyEntity)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param entity 存储数据的实例
     * @param <T>    实体类类型
     * @return 查到了就返回实例, 查不到返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, T entity) {
        String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
        return analysisResultSet(selectSql(sql).getResultSet(), colNames, entity);
//        try {
//            try (ResultSet resultSet = selectSql(sql).getResultSet()) {
//                Field[] fields = entity.getClass().getFields();
//                if (fields.length == 0) {
//                    return entity;
//                }
//                fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.ALL});
//                String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
//                if (resultSet.next()) {
//                    for (int i = 0; i < fields.length; i++) {
//                        String colName = getColNameFromField(fields[i]);
//                        boolean flag = false;
//                        for (String name : colNames) {
//                            if (colName.equals(name)) {
//                                flag = true;
//                                break;
//                            }
//                        }
//                        if (!flag) {
//                            continue;
//                        }
//                        try {
//                            if (fields[i].getAnnotation(JSONField.class) != null) {
//                                fields[i].set(entity, JSONUtil.jsonToObject(resultSet.getString(colName), fields[i].getType()));
//                                continue;
//                            }
//                            fields[i].set(entity, resultSet.getObject(colName));
//                        } catch (Exception e) {
//                            fields[i].set(entity, resultSet.getObject(colName).toString());
//                        }
//                    }
//                    return entity;
//                }
//                return null;
//            }
//        } catch (Exception e) {
//            if (isUseReminderMessage)
//                System.out.println("提醒:数据库查询失败:" + e.getMessage());
//            if (isEnableThrowError)
//                throw new RuntimeException(e);
//            if (isUseErrorStack)
//                e.printStackTrace();
//        }
//        return null;
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * @param sql      sql语句
     * @param colNames 需要查询的列名数组
     * @param entity   存储数据的实例
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, String[] colNames, T entity) {
        return analysisResultSet(selectSql(sql).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql(String, String[], Class)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param entity 实体类class
     * @param <T>    实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql(sql, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * @param sql      sql语句
     * @param colNames 需要查询的列名数组
     * @param entity   实体类class
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, String[] colNames, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql(sql, colNames, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql(String, Object[], String[], IMyEntity)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param map    映射数组
     * @param entity 存储数据的实例
     * @param <T>    实体类类型
     * @return 查到了就返回实例, 查不到返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, Object[] map, T entity) {
        String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
        return analysisResultSet(selectSql(sql, map).getResultSet(), colNames, entity);
        /*
        try {
            try (ResultSet resultSet = selectSql(sql, map).getResultSet()) {
                Field[] fields = entity.getClass().getFields();
                if (fields.length == 0) {
                    return entity;
                }
                fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.ALL});
                String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
                String colName;
                if (resultSet.next()) {
                    for (int i = 0; i < fields.length; i++) {
                        colName = getColNameFromField(fields[i]);
                        boolean flag = false;
                        for (String name : colNames) {
                            if (colName.equals(name)) {
                                flag = true;
                                break;
                            }
                        }
                        if (!flag) {
                            continue;
                        }
                        if (fields[i].getAnnotation(JSONField.class) != null) {
                            fields[i].set(entity, JSONUtil.jsonToObject(resultSet.getString(colName), fields[i].getType()));
                            continue;
                        }
                        try {
                            fields[i].set(entity, resultSet.getObject(colName));
                        } catch (Exception e) {
                            fields[i].set(entity, resultSet.getObject(colName).toString());
                        }
                    }
                    return entity;
                }
                return null;
            }
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据库查询失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
         */
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * @param sql      sql语句
     * @param map      映射数组
     * @param colNames 需要查询的列名数组
     * @param entity   实体类实例
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, Object[] map, String[] colNames, T entity) {
        return analysisResultSet(selectSql(sql, map).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql(String, Object[], String[], Class)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param map    映射数组
     * @param entity 实体类class
     * @param <T>    实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, Object[] map, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql(sql, map, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * @param sql      sql语句
     * @param map      映射数组
     * @param colNames 需要查询的列名数组
     * @param entity   实体类class
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果没有查询到的数据或者报错则返回null
     */
    public <T extends IMyEntity> T selectSql(String sql, Object[] map, String[] colNames, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql(sql, map, colNames, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取全部数据注入实体类,并返回列表
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectAll(String, String[], Class)}
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql sql语句
     * @param entityClass 实体类的class
     * @param <T> 实体类类型
     * @return 注入好的列表, 报错返回null
     */
    public <T extends IMyEntity> List<T> selectAll(String sql, Class<T> entityClass) {
        try {
            String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entityClass);
            return analysisResultSetReturnList(selectSql(sql).getResultSet(), colNames, entityClass);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取全部数据注入实体类,并返回列表
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql sql语句
     * @param colNames 列名数组
     * @param entityClass 实体类的class
     * @param <T> 实体类类型
     * @return 注入好的列表, 报错返回null
     */
    public <T extends IMyEntity> List<T> selectAll(String sql, String[] colNames, Class<T> entityClass) {
        try {
            return analysisResultSetReturnList(selectSql(sql).getResultSet(), colNames, entityClass);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取全部数据注入实体类,并返回列表
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectAll(String, Object[], String[], Class)}
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql sql语句
     * @param map 映射数组
     * @param entityClass 实体类的class
     * @param <T> 实体类类型
     * @return 注入好的列表, 报错返回null
     */
    public <T extends IMyEntity> List<T> selectAll(String sql, Object[] map, Class<T> entityClass) {
        try {
            String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entityClass);
            return analysisResultSetReturnList(selectSql(sql, map).getResultSet(), colNames, entityClass);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取全部数据注入实体类,并返回列表
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql sql语句
     * @param map 映射数组
     * @param colNames 列名数组
     * @param entityClass 实体类的class
     * @param <T> 实体类类型
     * @return 注入好的列表, 报错返回null
     */
    public <T extends IMyEntity> List<T> selectAll(String sql, Object[] map, String[] colNames, Class<T> entityClass) {
        try {
            return analysisResultSetReturnList(selectSql(sql, map).getResultSet(), colNames, entityClass);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }


    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql_upgrade(String, String[], IMyEntity)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param entity 存储数据的实例
     * @param <T>    实例类型
     * @return 查到了就返回实例, 查不到或报错返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, T entity) {
        String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
        return analysisResultSet_upgrade(selectSql(sql).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param colNames 需要查询的列名
     * @param entity   实体类
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果查不到或报错就返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, String[] colNames, T entity) {
        return analysisResultSet_upgrade(selectSql(sql).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql_upgrade(String, String[], Class)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param entity 实体类的class
     * @param <T>    实体类型
     * @return 注入好的实体类, 如果查不到或报错就返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql_upgrade(sql, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param colNames 需要查询的列名
     * @param entity   实体类class
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果查不到或报错就返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, String[] colNames, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql_upgrade(sql, colNames, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql_upgrade(String, Object[], String[], IMyEntity)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param map    映射数组
     * @param entity 存储数据的实例
     * @param <T>    实例类型
     * @return 查到了就返回实例, 查不到返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, Object[] map, T entity) {
        String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity.getClass());
        return analysisResultSet_upgrade(selectSql(sql, map).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param map      映射数组
     * @param colNames 需要查询的列名
     * @param entity   实体类实例
     * @param <T>      实体类类型
     * @return 查到了就返回实例, 查不到返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, Object[] map, String[] colNames, T entity) {
        return analysisResultSet_upgrade(selectSql(sql, map).getResultSet(), colNames, entity);
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 对于复杂的查询请使用
     * {@link MyJdbcUtil#selectSql_upgrade(String, Object[], String[], Class)}
     * <p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param map    映射集合
     * @param entity 实体类的class
     * @param <T>    实体类型
     * @return 注入好的实体类, 如果查不到或报错就返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, Object[] map, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql_upgrade(sql, map, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询返回匹配的第一条数据,兼容'?'占位符,直接返回实例
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param map      映射集合
     * @param colNames 需要查询的列名
     * @param entity   实体类class
     * @param <T>      实体类类型
     * @return 注入好的实体类, 如果查不到或报错就返回null
     */
    public <T extends IMyEntity> T selectSql_upgrade(String sql, Object[] map, String[] colNames, Class<T> entity) {
        try {
            T ins = entity.getConstructor().newInstance();
            return selectSql_upgrade(sql, map, colNames, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询全部信息并注入实体类,返回列表
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 注意:分组查询等比较复杂的查询请使用
     * {@link MyJdbcUtil#selectAll_upgrade(String, String[], Class)}
     * </p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    查询语句
     * @param entity 实体类class
     * @param <T>    实体类型
     * @return 实体类列表, 如果出错则返回null
     */
    public <T extends IMyEntity> List<T> selectAll_upgrade(String sql, Class<T> entity) {
        try {
            String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity);
            return analysisResultSetReturnList_upgrade(selectSql(sql).getResultSet(), colNames, entity);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询全部信息并注入实体类,返回列表
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param colNames 查询的列名
     * @param entity   实体类class
     * @param <T>      实体类类型
     * @return 实体类列表, 如果出错则返回null
     */
    public <T extends IMyEntity> List<T> selectAll_upgrade(String sql, String[] colNames, Class<T> entity) {
        try {
            return analysisResultSetReturnList_upgrade(selectSql(sql).getResultSet(), colNames, entity);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }


    /**
     * 查询全部信息并注入实体类,返回列表,兼容'?'占位符
     *
     * <p>支持封装类</p>
     *
     * <p>
     * 注意:分组查询等比较复杂的查询请使用
     * {@link MyJdbcUtil#selectAll_upgrade(String, Object[], String[], Class)}
     * </p>
     *
     * <p>
     * 如果查询语句使用'*'号则自动注入所有ColumnField类型是set或all的字段
     * <br/>
     * 如果查询语句标明列名,则只注入列名字段
     * <pre>{@code
     *     SELECT id,username,password FROM tb
     *     或者
     *     SELECT t.id,t.username,t.password FROM tb t
     *     均可,都会自动解析列名{id,username,password},
     *     但需要确保实体类中有id,username,password的字段
     * }<pre/>
     * </p>
     *
     * @param sql    sql语句
     * @param map    映射数组
     * @param entity 实体类class
     * @param <T>    实体类类型
     * @return 实体类列表, 如果出错返回null
     */
    public <T extends IMyEntity> List<T> selectAll_upgrade(String sql, Object[] map, Class<T> entity) {
        try {
            String[] colNames = getColNamesFromSelectSqlOrEntity(sql, entity);
            return analysisResultSetReturnList_upgrade(selectSql(sql, map).getResultSet(), colNames, entity);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询全部信息并注入实体类,返回列表
     *
     * <p>支持封装类</p>
     *
     * @param sql      sql语句
     * @param map      映射数组
     * @param colNames 需要注入的列名
     * @param entity   实体类class
     * @param <T>      实体类型
     * @return 实体类列表, 如果出错返回null
     */
    public <T extends IMyEntity> List<T> selectAll_upgrade(String sql, Object[] map, String[] colNames, Class<T> entity) {
        try {
            return analysisResultSetReturnList_upgrade(selectSql(sql, map).getResultSet(), colNames, entity);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:查询出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 把ResultSet注入到实体类中
     *
     * @param colNames  列名
     * @param resultSet 结果集
     * @param entity    实体类class
     * @param <T>       实体类类型
     * @return 注入好的实体类, 如果无数据或报错则返回null
     */
    @Deprecated
    private <T extends IMyEntity> T resultSetToEntity(String[] colNames, ResultSet resultSet, T entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        if (fields.length == 0) {
            return entity;
        }
        fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.ALL});
        Method[] methods = entity.getClass().getMethods();
        try {
            if (resultSet.next()) {
                for (Field field : fields) {
                    //过滤不查询的字段
                    String colName = getColNameFromField(field);
                    boolean flag = false;
                    for (String name : colNames) {
                        if (colName.equals(name)) {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        continue;
                    }
                    setFieldValue(entity, field, methods, resultSet.getObject(colName), true);

//                    SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
//                    Method setter = setterAndGetterFilterResult.setter;
//                    if (setter != null) {
//                        if (field.getAnnotation(JSONField.class) != null) {
//                            setter.invoke(entity, JSONUtil.jsonToObject(resultSet.getString(colName), field.getType()));
//                        } else {
//                            try {
//                                setter.invoke(entity, resultSet.getObject(colName));
//                            } catch (Exception e) {
//                                //如果类型匹配出现问题则尝试注入String类型,如果还是注入失败则报异常,然后被外围try-catch捕获,最后中断注入
//                                setter.invoke(entity, resultSet.getObject(colName).toString());
//                            }
//                        }
//                    }

//                    for (Method method : methods) {
//                        if (method.getName().equalsIgnoreCase("set" + field.getName())) {
//                            if (field.getAnnotation(JSONField.class) != null) {
//                                method.invoke(entity, JSONUtil.jsonToObject(resultSet.getString(colName), field.getType()));
//                                break;
//                            }
//                            try {
//                                method.invoke(entity, resultSet.getObject(colName));
//                            } catch (Exception e) {
//                                //如果类型匹配出现问题则尝试注入String类型,如果还是注入失败则报异常,然后被外围try-catch捕获,最后中断注入
//                                method.invoke(entity, resultSet.getObject(colName).toString());
//                            }
//                            break;
//                        }
//                    }
                }
                resultSet.close();
                return entity;
            }
            resultSet.close();
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据注入失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 从查询语句或者实体类中获取列名
     *
     * @param sql    查询语句
     * @param entity 实体类class
     * @param <T>    实体类型
     * @return 列名
     */
    private <T extends IMyEntity> String[] getColNamesFromSelectSqlOrEntity(String sql, Class<T> entity) {
        String[] colNames = null;
        String sqlLower = sql.toLowerCase();
        if (sqlLower.contains("from")) {
            String[] splits = sqlLower.split("from");
            String col = splits[0].replace("select", "")
                    .replace("distinct", "")
                    .trim();
            if (!col.contains("*")) {
                colNames = col.split(",");
                for (int i = 0; i < colNames.length; i++) {
                    String colName = colNames[i].trim();
                    if (colName.contains(".")) {
                        colName = colName.substring(colName.indexOf(".") + 1);
                        colNames[i] = colName.trim();
                    } else if (colName.contains("as")) {
                        colName = colName.substring(colName.indexOf("as") + 3);
                        colNames[i] = colName.trim();
                    } else if (colName.contains(" ")) {
                        int index = colName.indexOf(" ");
                        for (int j = index; j < colName.length(); j++) {
                            if (colName.charAt(j) == ' ') {
                                index = j;
                            } else {
                                break;
                            }
                        }
                        colName = colName.substring(index).trim();
                        colNames[i] = colName.trim();
                    } else {
                        colNames[i] = colName;
                    }
                }
            } else {
                Field[] fields = entity.getDeclaredFields();
                if (fields.length > 0) {
                    fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.ALL});
                    ArrayList<String> colList = new ArrayList<>();
                    String colName;
                    for (Field f : fields) {
                        colName = getColNameFromField(f);
                        colList.add(colName);
                    }
                    colNames = colList.toArray(new String[0]);
                }
            }
        }
        return colNames;
    }

    /**
     * 设置字段的值
     *
     * @param entity      实体类
     * @param field       字段
     * @param methods     方法数组
     * @param value       目标值
     * @param isUseSetter 是否使用setter方法
     * @param <T>         实体类类型
     * @throws Exception 异常
     */
    private <T extends IMyEntity> void setFieldValue(T entity, Field field, Method[] methods, Object value, boolean isUseSetter) throws Exception {
        if (isUseSetter) {
            SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
            Method setter = setterAndGetterFilterResult.setter;
            if (setter != null) {
                if (field.getAnnotation(JSONField.class) != null) {
                    setter.invoke(entity, JSONUtil.jsonToObject(value.toString(), field.getType()));
                } else {
                    try {
                        setter.invoke(entity, value);
                    } catch (Exception e) {
                        setter.invoke(entity, value.toString());
                    }
                }
            } else {
                throw new Exception("没有找到对应的setter方法");
            }
        } else {
            if (field.getAnnotation(JSONField.class) != null) {
                field.set(entity, JSONUtil.jsonToObject(value.toString(), field.getType()));
            } else {
                try {
                    field.set(entity, value);
                } catch (Exception e) {
                    field.set(entity, value.toString());
                }
            }
        }
    }

    /**
     * 获取字段的值
     *
     * @param entity      实体类
     * @param field       字段
     * @param methods     方法数组
     * @param isUseGetter 是否使用getter方法
     * @param <T>         实体类类型
     * @throws Exception 异常
     */
    private <T extends IMyEntity> Object getFieldValue(T entity, Field field, Method[] methods, boolean isUseGetter) throws Exception {
        if (isUseGetter) {
            SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
            Method getter = setterAndGetterFilterResult.getter;
            if (getter != null) {
                if (field.getAnnotation(JSONField.class) != null) {
                    return JSONUtil.objectToJson(getter.invoke(entity));
                } else {
                    return getter.invoke(entity);
                }
            } else {
                throw new Exception("没有找到对应的getter方法");
            }
        } else {
            if (field.getAnnotation(JSONField.class) != null) {
                return JSONUtil.objectToJson(field.get(entity));
            } else {
                return field.get(entity);
            }
        }
    }

    /**
     * 从字段数组中过滤主键字段
     *
     * @param fields 字段数组
     * @return 主键字段数组
     */
    private List<Field> getPrimaryKeyFields(Field[] fields) {
        List<Field> primaryKeyFields = new ArrayList<>();
        for (Field field : fields) {
            ColumnField annotation = field.getAnnotation(ColumnField.class);
            if (annotation != null) {
                if (annotation.isPrimaryKey()) {
                    primaryKeyFields.add(field);
                }
            }
        }
        return primaryKeyFields;
    }


    /**
     * 通过实体类更新数据
     *
     * <p>切记:实体类的字段推荐使用封装类型,非封装类型可能出现不必要的更改</p>
     *
     * @param entity      实体类
     * @param whereSql    where语句,例如 "WHERE id = 1"
     * @param whereValues 兼容'?'占位符的where值数组
     * @param <T>         实体类类型
     * @return 受影响的行数, 如果出错返回-1
     */
    public <T extends IMyEntity> int updateSql(T entity, String whereSql, Object[] whereValues) {
        try {
            String tableName = getTableNameFromClass(entity);
            Field[] fields = entity.getClass().getFields();
            if (fields.length == 0)
                return 0;
            fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.GET, ColumnField.Type.ALL});
            List<Field> primaryKeyFields = getPrimaryKeyFields(fields);
            if (primaryKeyFields.isEmpty() && whereSql == null) {
                throw new Exception("实体类没有主键,实体类updateSql方法无法更新");
            }
            StringBuilder sql = new StringBuilder();
            List<Object> values = new ArrayList<>();
            sql.append("UPDATE ").append(tableName).append(" SET ");
            for (Field field : fields) {
                //传入where语句时,不排除主键字段
                if (primaryKeyFields.contains(field) && whereSql == null)
                    continue;
                Object fieldValue = getFieldValue(entity, field, null, false);
                if (field.getAnnotation(JSONField.class) != null) {
                    if (fieldValue == null || fieldValue.toString().equals("null")) {
                        continue;
                    }
                }
                if (fieldValue != null) {
                    String colNameFromField = getColNameFromField(field);
                    sql.append(colNameFromField).append("=?,");
                    values.add(fieldValue);
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        values.add(JSONUtil.objectToJson(o));
//                    } else {
//                        values.add(o);
//                    }
                }
            }
            //删除多余的逗号
            sql.deleteCharAt(sql.length() - 1);
            if (whereSql == null) {
                StringBuilder whereSqlSB = new StringBuilder(" WHERE ");
                int preN = whereSqlSB.length();
                for (Field field : primaryKeyFields) {
                    Object fieldValue = getFieldValue(entity, field, null, false);
                    if (field.getAnnotation(JSONField.class) != null) {
                        if (fieldValue == null || fieldValue.toString().equals("null")) {
                            continue;
                        }
                    }
                    if (fieldValue == null) {
                        continue;
                    }
                    String colNameFromField = getColNameFromField(field);
                    whereSqlSB.append(colNameFromField).append("=? AND ");
                    values.add(fieldValue);
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        values.add(JSONUtil.objectToJson(o));
//                    } else {
//                        values.add(o);
//                    }
                }
                int n = whereSqlSB.length();
                //删除多余的AND
                whereSqlSB.delete(n - 5, n);
                if (n > preN) {
                    sql.append(whereSqlSB);
                }
            } else {
                sql.append(" ").append(whereSql);
                if (whereValues != null && whereValues.length > 0) {
                    values.addAll(Arrays.asList(whereValues));
                }
            }
            return updateSql(sql.toString(), values.toArray());
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:实体类updateSql方法出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 通过实体类更新数据
     *
     * <p>默认通过主键插入,请在实体类中指明主键</p>
     *
     * <p>切记:实体类的字段推荐使用封装类型,非封装类型可能出现不必要的更改</p>
     *
     * @param entity 实体类
     * @param <T>    实体类类型
     * @return 受影响的行数, 如果出错返回-1
     */
    public <T extends IMyEntity> int updateSql(T entity) {
        return updateSql(entity, null, null);
    }

    /**
     * 通过实体类更新数据
     *
     * <p>切记:实体类的字段推荐使用封装类型,非封装类型可能出现不必要的更改</p>
     *
     * <p>支持封装类</p>
     *
     * @param entity      实体类
     * @param whereSql    where语句,例如 "WHERE id = 1"
     * @param whereValues 兼容'?'占位符的where值数组
     * @param <T>         实体类类型
     * @return 受影响的行数, 如果出错返回-1
     */
    public <T extends IMyEntity> int updateSql_upgrade(T entity, String whereSql, Object[] whereValues) {
        try {
            String tableName = getTableNameFromClass(entity);
            Field[] declaredFields = entity.getClass().getDeclaredFields();
            declaredFields = fieldFilter(declaredFields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.GET, ColumnField.Type.ALL});
            List<Field> primaryKeyFields = getPrimaryKeyFields(declaredFields);
            if (whereSql == null && primaryKeyFields.isEmpty()) {
                throw new Exception("实体类没有主键,实体类updateSql方法无法更新");
            }
            StringBuilder sql = new StringBuilder();
            List<Object> values = new ArrayList<>();
            sql.append("UPDATE ").append(tableName).append(" SET ");
            Method[] methods = entity.getClass().getMethods();
            for (Field field : declaredFields) {
                //传入where语句时,不排除主键字段
                if (primaryKeyFields.contains(field) && whereSql == null) {
                    continue;
                }
                Object fieldValue = getFieldValue(entity, field, methods, true);
                if (field.getAnnotation(JSONField.class) != null) {
                    if (fieldValue == null || fieldValue.toString().equals("null")) {
                        continue;
                    }
                }
                if (fieldValue != null) {
                    String colNameFromField = getColNameFromField(field);
                    sql.append(colNameFromField).append("=?,");
                    values.add(fieldValue);
                }
//                SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
//                Object invoke = setterAndGetterFilterResult.getter.invoke(entity);
//                if (invoke != null) {
//                    String colNameFromField = getColNameFromField(field);
//                    sql.append(colNameFromField).append("=?,");
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        values.add(JSONUtil.objectToJson(invoke));
//                    } else {
//                        values.add(invoke);
//                    }
//                }
            }
            //删除多余的逗号
            sql.deleteCharAt(sql.length() - 1);
            if (whereSql == null) {
                StringBuilder whereSqlSB = new StringBuilder(" WHERE ");
                int preN = whereSqlSB.length();
                for (Field field : primaryKeyFields) {
                    Object fieldValue = getFieldValue(entity, field, methods, true);
                    if (field.getAnnotation(JSONField.class) != null) {
                        if (fieldValue == null || fieldValue.toString().equals("null")) {
                            continue;
                        }
                    }
                    if (fieldValue != null) {
                        String colNameFromField = getColNameFromField(field);
                        whereSqlSB.append(colNameFromField).append("=? AND ");
                        values.add(fieldValue);
                    }
//                    SetterAndGetterFilterResult setterAndGetterFilterResult = setterAndGetterFilter(methods, field);
//                    Object invoke = setterAndGetterFilterResult.getter.invoke(entity);
//                    if (invoke != null) {
//                        String colNameFromField = getColNameFromField(field);
//                        whereSqlSB.append(colNameFromField).append("=? AND ");
//                        if (field.getAnnotation(JSONField.class) != null) {
//                            values.add(JSONUtil.objectToJson(invoke));
//                        } else {
//                            values.add(invoke);
//                        }
//                    }
                }
                //删除多余的AND
                int n = whereSqlSB.length();
                whereSqlSB.delete(n - 5, n);
                if (n > preN) {
                    sql.append(whereSqlSB);
                }
            } else {
                sql.append(" ").append(whereSql);
                if (whereValues != null && whereValues.length > 0) {
                    values.addAll(Arrays.asList(whereValues));
                }
            }
            return updateSql(sql.toString(), values.toArray());
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:实体类updateSql方法出错:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return -1;
    }

    /**
     * 通过实体类更新数据
     *
     * <p>默认通过主键插入,请在实体类中指明主键</p>
     *
     * <p>切记:实体类的字段推荐使用封装类型,非封装类型可能出现不必要的更改</p>
     *
     * <p>支持封装类</p>
     *
     * @param entity 实体类
     * @param <T>    实体类类型
     * @return 受影响的行数, 如果出错返回-1
     */
    public <T extends IMyEntity> int updateSql_upgrade(T entity) {
        return updateSql_upgrade(entity, null, null);
    }

    //endregion

    //#region 解析ResultSet

    /**
     * 解析ResultSet,把ResultSet转为行列表
     *
     * @param resultSet 查询结果集
     * @param colName   需要解析的列名
     * @return 每行数据, 行数据和输入的列名相对应, 转换失败返回null
     */
    public ArrayList<Object[]> analysisResultSet(ResultSet resultSet, String[] colName) {
        if (resultSet == null || colName == null || colName.length == 0)
            return null;
        ResultSetManager.addNewResultSet(resultSet, null);
        ArrayList<Object[]> re = new ArrayList<>();
        try {
            while (resultSet.next()) {
                Object[] row = new Object[colName.length];
                int i = 0;
                for (String col : colName) {
                    row[i++] = resultSet.getObject(col);
                }
                re.add(row);
            }
            return re;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据ResultSet解析失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet,自动注入实体类,注意只会注入一行数据,
     * 即使有多行也只注入最上面的那行数据
     *
     * @param resultSet 结果集
     * @param colNames  需要解析的列名
     * @param entity    实体类
     * @param <T>       实体类类型
     * @return 注入好的实体类, 如果没有数据或转换失败返回null
     */
    public <T extends IMyEntity> T analysisResultSet(ResultSet resultSet, String[] colNames, T entity) {
        if (resultSet == null || colNames == null || colNames.length == 0)
            return null;
        ResultSetManager.addNewResultSet(resultSet, null);
        try {
            Field[] fields = entity.getClass().getFields();
            if (fields.length == 0) {
                return entity;
            }
            fields = fieldFilter(fields, new ColumnField.Type[]{ColumnField.Type.SET, ColumnField.Type.ALL});
            String colName;
            if (resultSet.next()) {
                for (String col : colNames) {
                    for (Field field : fields) {
                        colName = getColNameFromField(field);
                        if (colName.equals(col)) {
                            setFieldValue(entity, field, null, resultSet.getObject(col), false);
                            break;
//                            if (field.getAnnotation(JSONField.class) != null) {
//                                field.set(entity, JSONUtil.jsonToObject(resultSet.getString(col), field.getType()));
//                                break;
//                            }
//                            field.set(entity, resultSet.getObject(col));
                        }
                    }
                }
                return entity;
            }
            return null;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据ResultSet解析失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet,自动注入实体类,注意只会注入一行数据
     * ,即使有多行也只注入最上面的那行数据
     *
     * @param resultSet   结果集
     * @param colNames    需要解析的列名
     * @param entityClass 实体类class
     * @param <T>         实体类类型
     * @return 注入好的实体类, 如果没有数据或报错则返回null
     */
    public <T extends IMyEntity> T analysisResultSet(ResultSet resultSet, String[] colNames, Class<T> entityClass) {
        try {
            if (resultSet == null || colNames == null || colNames.length == 0)
                return null;
            ResultSetManager.addNewResultSet(resultSet, null);
            T t = entityClass.getConstructor().newInstance();
            return analysisResultSet(resultSet, colNames, t);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据ResultSet解析失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet并自动注入到实体类中,返回结果列表
     *
     * @param resultSet   结果集
     * @param colNames    列名数组
     * @param entityClass 目标class
     * @param <T>         实体类类型
     * @return 结果列表, 报错返回null
     */
    public <T extends IMyEntity> List<T> analysisResultSetReturnList(ResultSet resultSet, String[] colNames, Class<T> entityClass) {
        try {
            if (resultSet == null)
                return null;
            ResultSetManager.addNewResultSet(resultSet, null);
            if (colNames == null || colNames.length == 0) {
                return new ArrayList<>();
            }
            List<T> re = new ArrayList<>();
            while (!resultSet.isLast()) {
                T t = analysisResultSet(resultSet, colNames, entityClass);
                if (t == null) {
                    break;
                }
                re.add(t);
            }
            return re;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据ResultSet解析失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet,自动注入实体类,注意只会注入一行数据,
     * 即使有多行也只注入最上面的那行数据
     *
     * <p>支持封装类</p>
     *
     * @param resultSet 结果集
     * @param colNames  需要解析的列名
     * @param entity    实体类
     * @param <T>       实体类类型
     * @return 注入好的实体类, 如果没有数据或转换失败返回null
     */
    public <T extends IMyEntity> T analysisResultSet_upgrade(ResultSet resultSet, String[] colNames, T entity) {
        if (resultSet == null || colNames == null || colNames.length == 0)
            return null;
        ResultSetManager.addNewResultSet(resultSet, null);
        try {
            Method[] methods = entity.getClass().getMethods();
            Field[] fields = entity.getClass().getDeclaredFields();
            if (resultSet.next()) {
                for (String col : colNames) {
                    for (Field field : fields) {
                        String colNameFromField = getColNameFromField(field);
                        if (col.equals(colNameFromField)) {
                            setFieldValue(entity, field, methods, resultSet.getObject(col), true);
                            break;
                        }
                    }
//                    SetterAndGetterFilterResult setterFilterResult = setterAndGetterFilter(methods, fields, col);
//                    if (setterFilterResult == null || setterFilterResult.setter == null) {
//                        throw new Exception("注入失败,找不到字段的setter方法:" + col);
//                    }
//                    Method method = setterFilterResult.setter;
//                    Field field = setterFilterResult.field;
//                    if (field.getAnnotation(JSONField.class) != null) {
//                        method.invoke(entity, JSONUtil.jsonToObject(resultSet.getString(col), field.getType()));
//                        continue;
//                    }
//                    method.invoke(entity, resultSet.getObject(col));
                }
                return entity;
            }
            return null;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:数据ResultSet解析失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet,自动注入实体类,注意只会注入一行数据,
     * 即使有多行也只注入最上面的那行数据
     *
     * <p>支持封装类</p>
     *
     * @param resultSet   结果集
     * @param colName     列名
     * @param entityClass 实体类class
     * @param <T>         实体类型
     * @return 注入好的实体类, 如果没有数据或转换失败返回null
     */
    public <T extends IMyEntity> T analysisResultSet_upgrade(ResultSet resultSet, String[] colName, Class<T> entityClass) {
        try {
            ResultSetManager.addNewResultSet(resultSet, null);
            T ins = entityClass.getConstructor().newInstance();
            return analysisResultSet_upgrade(resultSet, colName, ins);
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:解析ResultSet失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 解析ResultSet,自动注入实体类,返回结果列表
     *
     * <p>支持封装类</p>
     *
     * @param resultSet   结果集
     * @param colNames    列名
     * @param entityClass 实体类class
     * @param <T>         实体类型
     * @return 实体类列表, 如果出错返回null
     */
    public <T extends IMyEntity> List<T> analysisResultSetReturnList_upgrade(ResultSet resultSet, String[] colNames, Class<T> entityClass) {
        try {
            if (resultSet == null)
                return null;
            ResultSetManager.addNewResultSet(resultSet, null);
            List<T> list = new ArrayList<>();
            if (colNames == null || colNames.length == 0) {
                return list;
            }
            while (!resultSet.isLast()) {
                T t = analysisResultSet_upgrade(resultSet, colNames, entityClass);
                if (t == null) {
                    break;
                }
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            if (isUseReminderMessage)
                System.out.println("提醒:解析ResultSet失败:" + e.getMessage());
            if (isEnableThrowError)
                throw new RuntimeException(e);
            if (isUseErrorStack)
                e.printStackTrace();
        }
        return null;
    }

    /**
     * 过滤setter和getter方法
     *
     * @param method  方法组
     * @param fields  字段组
     * @param colName 目标列名
     * @return 结构, 找不到匹配字段返回null
     */
    private SetterAndGetterFilterResult setterAndGetterFilter(Method[] method, Field[] fields, String colName) {
        String colName_field;
        Field field = null;
        for (Field f : fields) {
            colName_field = getColNameFromField(f);
            if (colName_field.equals(colName)) {
                field = f;
                break;
            }
        }
        if (field == null) {
            return null;
        }
        return setterAndGetterFilter(method, field);
    }

    /**
     * 过滤setter和getter方法
     *
     * @param method 方法组
     * @param field  字段
     * @return 结果保证非空
     */
    private SetterAndGetterFilterResult setterAndGetterFilter(Method[] method, Field field) {
        String name = field.getName();
        Method setter = null;
        Method getter = null;
        for (Method m : method) {
            if (setter == null && m.getName().equalsIgnoreCase("set" + name)) {
                setter = m;
            }
            if (getter == null && m.getName().equalsIgnoreCase("get" + name)) {
                getter = m;
            }
            if (getter != null && setter != null) {
                break;
            }
        }
        return new SetterAndGetterFilterResult(setter, getter, field);
    }

    /**
     * setter过滤结构
     */
    private static class SetterAndGetterFilterResult {
        public Method setter;
        public Method getter;
        public Field field;

        public SetterAndGetterFilterResult(Method setter, Method getter, Field field) {
            this.setter = setter;
            this.getter = getter;
            this.field = field;
        }
    }

//#endregion

    /**
     * 判断是否是数值型或布尔型,用于判断此类型是否需要加''号
     *
     * @param targetField 目标字段class文件
     * @return 是否需要加引号
     */
    @Deprecated
    private boolean isNotNeedAddQuotationMarks(Class<?> targetField) {
        return targetField.equals(Number.class) ||
                targetField.getSuperclass().equals(Number.class) ||
                targetField.equals(Boolean.class) ||
                targetField.isPrimitive();
    }

    /**
     * 类名转表名,即'大驼峰'转'_分割命名'
     *
     * @param entity 实体类
     * @param <T>    实体类型
     * @return 转换的表名
     */
    private <T extends IMyEntity> String classNameToTableName(T entity) {
        String tableName;
        StringBuilder tb = new StringBuilder();
        String className = entity.getClass().getSimpleName();
        tb.append(className.charAt(0));
        for (int i = 1; i < className.length(); i++) {
            if (Character.isUpperCase(className.charAt(i))) {
                tb.append("_");
            }
            tb.append(className.charAt(i));
        }
        tableName = tb.toString().toLowerCase();
        return tableName;
    }

    /**
     * 小驼峰转下划线命名
     *
     * @param name 小驼峰命名
     * @return 下划线命名
     */
    private String littleHumpReplace(String name) {
        StringBuilder sb = new StringBuilder();
        for (char c : name.toCharArray()) {
            if (Character.isUpperCase(c)) {
                sb.append("_");
            }
            sb.append(c);
        }
        return sb.toString().toLowerCase();
    }
}